package com.hongye.why.base;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
import android.os.Environment;
import android.os.Looper;
import android.util.Log;

import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.Thread.UncaughtExceptionHandler;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.TimeZone;

/**
 * 程序崩溃处理工具
 */
public class CrashHandler implements UncaughtExceptionHandler {
	private Context mContext;
	private static final String SDCARD_ROOT = Environment.getExternalStorageDirectory().toString();
	private static CrashHandler mInstance = new CrashHandler();
	private Thread.UncaughtExceptionHandler mDefaultHandler;

	private CrashHandler() {
		mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
	}

	public static CrashHandler getInstance() {
		return mInstance;
	}

	public static void init(Context context) {
		getInstance().setCustomCrashHanler(context);
	}

	@SuppressWarnings("static-access")
	@Override
	public void uncaughtException(Thread thread, Throwable ex) {
		savaInfoToSD(mContext, ex);
        try {
            thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
		ActivityStack.finishAll();
        System.exit(0);
//		if (!handleException(ex) && null != mDefaultHandler) {
//			mDefaultHandler.uncaughtException(thread, ex);
//		} else {
//			savaInfoToSD(mContext, ex);

            //当前没有界面，不自动重启进程
//			if (ActivityCollector.size() == 0){
//				return;
//			}
//			LogUtil.e(ex.getMessage());
//			//showToast(mContext, "");
//			try {
//				thread.sleep(2000);
//			} catch (InterruptedException e) {
//				e.printStackTrace();
//			}
//
//			if (MyApplication.getApplication().isForeground()) {//待发现应用在前台重启
//				Intent intent = new Intent(mContext.getApplicationContext(), WelcomeActivity.class);
//	            PendingIntent restartIntent = PendingIntent.getActivity(mContext.getApplicationContext(), 0, intent, Intent.FLAG_ACTIVITY_NEW_TASK);
//
//	            AlarmManager mgr = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
//	            mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000,restartIntent); // 1秒钟后重启应用
//			}
//			 //退出程序
//			ImageCache.getInstance().clear();
//			ActivityCollector.finishAll();
//			System.exit(0);
//		}
	}
	
	
	
	 /**  
     * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.  
     *   
     * @param ex  
     * @return true:如果处理了该异常信息;否则返回false.  
     */    
    private boolean handleException(Throwable ex) {
        if (ex == null) {    
            return false;    
        }    
        //使用Toast来显示异常信息    
        new Thread(){
            @Override
            public void run() {    
                Looper.prepare();
//                MyApplication app = MyApplication.getApplication();
//
//                if (app != null && app.isForeground()) {
//                	Toast.makeText(mContext, "很抱歉,程序出现异常,即将重启.",
//                            Toast.LENGTH_SHORT).show();
//				}
//                Looper.loop();
            }   
        }.start();    
        return true;    
    }    

	private void setCustomCrashHanler(Context context) {
		mContext = context;
		Thread.setDefaultUncaughtExceptionHandler(this);
	}

	private void showToast(final Context context, final int resId) {
		new Thread(new Runnable() {

			@Override
			public void run() {
				// Looper.prepare();
				// Toast.makeText(context, resId, Toast.LENGTH_LONG).show();
				// Looper.loop();
			}
		}).start();
	}

	/**
	 * 获取运行环境基本信息
	 * @param context
	 * @return
	 */
	private HashMap<String, String> obtainSimpleInfo(Context context) {
		HashMap<String, String> map = new HashMap<String, String>();
		PackageManager mPackageManager = context.getPackageManager();
		PackageInfo mPackageInfo = null;
		try {
			mPackageInfo = mPackageManager.getPackageInfo(context.getPackageName(), PackageManager.GET_ACTIVITIES);
		} catch (NameNotFoundException e) {
			e.printStackTrace();
			return map;
		}

		map.put("versionName", mPackageInfo.versionName);
		map.put("versionCode", "" + mPackageInfo.versionCode);

		map.put("MODEL", "" + Build.MODEL);
		map.put("SDK_INT", "" + Build.VERSION.SDK_INT);
		map.put("PRODUCT", "" + Build.PRODUCT);

		return map;
	}

	/**
	 * 获取异常信息
	 * @param throwable 异常
	 * @return String 异常信息
	 */
	private String obtainExceptionInfo(Throwable throwable) {
		StringWriter mStringWriter = new StringWriter();
		PrintWriter mPrintWriter = new PrintWriter(mStringWriter);
		throwable.printStackTrace(mPrintWriter);
		mPrintWriter.close();

		Log.e("CrashHandler", mStringWriter.toString());
		return mStringWriter.toString();
	}

	/**
	 * 将异常以文本的形式保存到本地
	 * @param context
	 * @param ex 异常
	 * @return String 保存的异常文件名
	 */
	private String savaInfoToSD(Context context, Throwable ex) {
		String fileName = null;
		StringBuffer sb = new StringBuffer();

		for (Map.Entry<String, String> entry : obtainSimpleInfo(context).entrySet()) {
			String key = entry.getKey();
			String value = entry.getValue();
			sb.append(key).append(" = ").append(value).append("\n");
		}

		sb.append(obtainExceptionInfo(ex));

		if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
			File dir = new File(SDCARD_ROOT + File.separator + "crash" + File.separator);
			if (!dir.exists()) {
				dir.mkdir();
			}

			try {
				fileName = dir.toString() + File.separator + parseTime(System.currentTimeMillis()) + ".txt";
				FileOutputStream fos = new FileOutputStream(fileName);
				fos.write(sb.toString().getBytes());
				fos.flush();
				fos.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		return fileName;
	}

	/**
	 * 将毫秒转换成可观的时间格式
	 * @param milliseconds
	 * @return String 日期时间 格式：yyyy-MM-dd-HH-mm-ss
	 */
	@SuppressLint("SimpleDateFormat")
	private String parseTime(long milliseconds) {
		System.setProperty("user.timezone", "Asia/Shanghai");
		TimeZone tz = TimeZone.getTimeZone("Asia/Shanghai");
		TimeZone.setDefault(tz);
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
		return format.format(new Date(milliseconds));
	}
}
